package com.livestocksolutions;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

import com.livestocksolutions.util.UpdateHistory;

/* -- Version History --
 *  1.0 : 15 July 2012 - Initial version.
 *  
 *  1.1 : 16 July 2012 - Class now implements Serializable
 *  
 *  1.2 : 05 September 2012 - Changed private Group group to private long group
 *  
 *  1.3 : 22 September 2012 - Added methods and attributes to track changes. Removed modified attributes introduced
 *                       in previous version.
 *                       Serialisation method no longer requires GroupHistory implementing Serializable.
 */

/**
 * Creates an Object that tracks the date the animal enters
 * and exits the particular group provided
 * @author Adam Parr
 * 
 * @version 1.3
 * 
 * @.modified 22 September 2012
 */
public class GroupHistory{
	/**
	 * The Group or Mob this Animal belongs to
	 */
	private long group;
	/**
	 * The date this Animal went into this Group or Mob
	 */
	private long entryDate;
	/**
	 * The date this Animal left this Group or Mob
	 */
	private long exitDate;
	
	/**
	 * Unique ID that identifies this Owner
	 */
	protected final long id;
	/**
	 * Keep track of any changes of this GroupHistory.
	 */
	protected HashMap<String,UpdateHistory> update = new HashMap<String,UpdateHistory>();
	/**
	 * Store the Owners ID.
	 */
	protected long owner;
	
	/**
	 * Create a GroupHistory, and allocate this Animal to the group
	 * provided starting from the given date.
	 * @param group The Group this animal is allocated to
	 * @param entryDate The date this animal went into this group
	 */
	public GroupHistory(Group group, Date entryDate){
		this.group=group.getID();
		this.entryDate=entryDate.getTime();

		id = Calendar.getInstance().getTimeInMillis();
	
		update.put("ID", new UpdateHistory(String.valueOf(id)));
		update.put("ENTRYDATE", new UpdateHistory(String.valueOf(this.entryDate)));
		update.put("GROUP", new UpdateHistory(String.valueOf(this.group)));
	}
	
	/**
	 * Get the Group that this history belongs to
	 * @return Group the animal was in between entryDate and exitDate
	 */
	public Group getGroup(){
		return LivestockSolutions.getGroupByID(group);
	}
	
	/**
	 * Get the Date the animal was added to the group
	 * @return A Date, on which this animal was placed into the associated group
	 */
	public Date getEntryDate(){
		return entryDate==0?null:new Date(entryDate);
	}
	
	/**
	 * Get the Date the animal was removed from this group
	 * @return A Date, on which this animal was removed from the associated group
	 */
	public Date getExitDate(){
		return exitDate==0?null:new Date(exitDate);
	}
	
	/**
	 * Set the date this animal was taken out of this group
	 * @param date the date the animal was removed from the group
	 * @return <code>true</code> if exit date had not been set before, otherwise
	 * <code>false</code> if the exit date had already been set prior to this.
	 */
	public boolean setExitDate(Date date){
		if(exitDate==0 || new Date(exitDate).after(new Date(entryDate))){
			exitDate=date.getTime();
			update.put("EXITDATE", new UpdateHistory(String.valueOf(exitDate)));
			return true;
		}
		return false;
	}
	
	/**
	 * Get the unique id of this GroupHistory
	 * @return the id of this GroupHistory
	 */
	public long getID(){
		return id;
	}
	
	/**
	 * Set the owner of this GroupHistory to a Bovine type
	 * @param owner The Bovine that this GroupHistory belongs to
	 */
	public void setOwner(Bovine owner){
		this.owner = owner.getID();
		update.put("OWNER", new UpdateHistory(String.valueOf(this.owner)));
	}
	
	/**
	 * Updates this Object with the updated values from the different version.
	 * @param changes GroupHistory that represents this Object in a different version.
	 * @return <tt>true</tt>.
	 */
	public boolean update(GroupHistory changes){
		if(changes!=null && this!=changes){
			if(updateBefore("OWNER",changes)){
				owner=Long.parseLong(changes.update.get("OWNER").getValue());
				update.put("OWNER", new UpdateHistory(String.valueOf(owner)));
			}
			
			if(updateBefore("ENTRYDATE",changes)){
				entryDate=Long.parseLong(changes.update.get("ENTRYDATE").getValue());
				update.put("ENTRYDATE", new UpdateHistory(String.valueOf(entryDate)));
			}
			
			if(updateBefore("EXITDATE",changes)){
				exitDate=Long.parseLong(changes.update.get("EXITDATE").getValue());
				update.put("EXITDATE", new UpdateHistory(String.valueOf(exitDate)));
			}
			return true;
		}
		return false;
	}
	
	/**
	 * Checks to see if the modification date of the item at this position is before the changed value
	 * @param key The String key at which to compare the modification dates of the modified objects.
	 * @param changes The GroupHistory that represents this GroupHistory on another system.
	 * @return <tt>true</tt> if the old value was modified before the changed value. <tt>false</tt> otherwise.
	 */
	protected boolean updateBefore(String key,GroupHistory changes){
		if(this.update.get(key)==null && changes.update.get(key)!=null){
			return true;
		}else if(changes.update.get(key)==null){
			return false;
		}
		return !this.update.get(key).getDate().after(changes.update.get(key).getDate());
	}
}